﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace Main
{
    class Program
    {
        static void Main(string[] args)
        {
            PrintAssemlyCount();
            PrintA();
            PrintB();
            PrintC();
            PrintD();
            PrintE();
            PrintF();
            PrintG();
            PrintH();
            PrintJ();
            PrintL();
            PrintM();
        }

        private static void PrintA()
        {
            Console.WriteLine("\nA.dll 位于 BaseDirectory，使用 default context 算法加载程序集。");
            Console.WriteLine(typeof(A.ClassA));
            PrintAssemlyCount();
        }

        private static void PrintB()
        {
            Console.WriteLine("\nB.dll 位于 BaseDirectory，使用 default context 算法加载程序集。");
            Console.WriteLine(Type.GetType("B.ClassB, B"));
            PrintAssemlyCount();
        }

        private static void PrintC()
        {
            Console.WriteLine("\nC.dll 位于 BaseDirectory\\C，使用 default context 算法加载程序集。。");
            Console.WriteLine(Type.GetType("C.ClassC, C"));
            PrintAssemlyCount();
        }

        private static void PrintD()
        {
            Console.WriteLine("\nD.dll 位于 BaseDirectory\\D_，配置了：<probing privatePath=\"D_\" />，使用 default context 算法加载程序集。");
            Console.WriteLine(Type.GetType("D.ClassD, D"));
            PrintAssemlyCount();
        }

        private static void PrintE()
        {
            Console.WriteLine("\nE.dll 位于 BaseDirectory\\E_，调用了：AppDomain.CurrentDomain.AppendPrivatePath(\"E_\")，使用 default context 算法加载程序集。");
            AppDomain.CurrentDomain.AppendPrivatePath("E_");
            Console.WriteLine(Type.GetType("E.ClassE, E"));
            PrintAssemlyCount();
        }

        private static void PrintF()
        {
            Console.WriteLine("\nLoadFile：使用 no context 算法加载程序集，只要路径不同，会返回多个相同程序集标识的程序集实例");
            Assembly.LoadFile(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\F_\F.dll");
            PrintAssemlyCount();
            Assembly.LoadFile(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\F__\F.dll");
            PrintAssemlyCount();
        }

        private static void PrintG()
        {
            Console.WriteLine("\nLoadFrom：使用 load-from context 算法加载程序集，如果两个路径下的程序集标识一样，只会返回一个程序集实例。");
            
            Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\G_\G.dll");
            PrintAssemlyCount();
            Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\G__\G.dll");
            PrintAssemlyCount();

            Console.WriteLine("\nLoadFrom：default context 和 load-from context 可以独立包含相同标识的程序集的程序集实例。");
            Type.GetType("G.ClassG, G");
            PrintAssemlyCount();
        }

        private static void PrintH()
        {
            Console.WriteLine("\nLoadFrom：使用 load-from context 算法加载程序集，会自动加载其依赖的程序集，其依赖的程序集的加载过程如下：以 “I” 为例，先使用 default context 算法查找 “I”，如果没有找到，再使用 load-from context 算法查找 “I”，如果找到了 “I” 且 load-from context 中有和 “I” 相同标识的程序集，返回 load-from context 中和 “I” 相同标识的程序集，如果找到了 “I” 且 load-from context 中没有和 “I” 相同标识的程序集，将 “I” 加载到相应的 context 并返回 “I” ，否则，加载失败。");
            var hAss = Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\H\bin\Debug\H.dll");
            PrintAssemlyCount();

            Activator.CreateInstance(hAss.GetTypes().First(x => x.Name == "ClassH"));
            PrintAssemlyCount();
        }

        private static void PrintJ()
        {
            Console.WriteLine("\nLoadFrom：使用 load-from context 算法加载程序集，会自动加载其依赖的程序集，其依赖的程序集的加载过程如下：以 “I” 为例，先使用 default context 算法查找 “I”，如果没有找到，再使用 load-from context 算法查找 “I”，如果找到了 “I” 且 load-from context 中有和 “I” 相同标识的程序集，返回 load-from context 中和 “I” 相同标识的程序集，如果找到了 “I” 且 load-from context 中没有和 “I” 相同标识的程序集，将 “I” 加载到相应的 context 并返回 “I” ，否则，加载失败。");
            Type.GetType("K.ClassK, K");
            var jAss = Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\J\bin\Debug\J.dll");
            PrintAssemlyCount();
            Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\K\bin\Debug\K.dll");
            PrintAssemlyCount();

            Activator.CreateInstance(jAss.GetTypes().First(x => x.Name == "ClassJ"));
        }

        private static void PrintL()
        {
            Console.WriteLine("\n加载私有部署的强名称程序集，配置了：<codeBase version=\"1.0.0.0\" href=\"file:///E:/Coding/HappyStudy/AssemblyStudy/L/bin/Debug/L.dll\" />，使用 default context 算法加载程序集。");
            Console.WriteLine(Type.GetType("L.ClassL, L, Version=1.0.0.0, Culture=neutral, PublicKeyToken=357f90d80abcd77e").Assembly.Location);
            PrintAssemlyCount();

            Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\L_\L.dll");
            PrintAssemlyCount();

            Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\Main\bin\Debug\L__\L.dll");
            PrintAssemlyCount();
        }

        private static void PrintM()
        {
            Console.WriteLine("\nLoadFrom：会自动加载依赖的程序集，其依赖的程序集和其依赖的程序集的依赖的程序集都采用相同的加载策略。");
            var mAss = Assembly.LoadFrom(@"E:\Coding\HappyStudy\AssemblyStudy\M\bin\Debug\M.dll");
            PrintAssemlyCount();

            Activator.CreateInstance(mAss.GetTypes().First(x => x.Name == "ClassM"));
            PrintAssemlyCount();
        }

        private static void PrintAssemlyCount()
        {
            Console.WriteLine("assembly count:" + AppDomain.CurrentDomain.GetAssemblies().Count());
        }
    }
}
